﻿#pragma once

#define DUI_DECLARE_WND_CLASS(WndClassName, WndClassStyle,szXmlFileName) \
  LPCTSTR GetWindowClassName() const override { return WndClassName; } \
  UINT GetClassStyle() const override { return WndClassStyle; } \
  CDuiString GetSkinFile() override { return szXmlFileName; } \
  CDuiString GetSkinFolder() override { return L""; }


//quick控件diy
#define BEGIN_DUICONTROL_CREATE() \
virtual CControlUI* CreateControl(LPCTSTR pstrClass) override{\
CDuiString tag_name_outter = pstrClass;\

#define DUICONTROL_CREATE(tag_name, ClassName) \
if (!tag_name_outter.CompareNoCase(tag_name)) \
return new ClassName;

#define END_DUICONTROL_CREATE() \
return NULL; \
}

#define END_DUICONTROL_CREATE_SUPER() \
return __super::CreateControl(pstrClass); \
}


class WindowImpl : public WindowImplBase
{
public:
  inline CPaintManagerUI& __PM() { return m_PaintManager; }

  template<typename N>
  CControlUI* FindControl(const N& clue)
  {
    return __PM().FindControl(clue);
  }

  template<typename N, typename V>
  bool FindControl(const N& clue, V*& control)
  {
    control = static_cast<V *>(__PM().FindControl(clue));
    return control != nullptr;
  }

  void SendNotify(CControlUI* pControl, LPCTSTR pstrMessage, WPARAM wParam = 0, LPARAM lParam = 0, bool bAsync = false)
  {
    return __PM().SendNotify(pControl, pstrMessage, wParam, lParam, bAsync);
  }

  BOOL ModifyStyle(
    _In_ DWORD dwRemove,
    _In_ DWORD dwAdd,
    _In_ UINT nFlags = 0) throw()
  {
    ATLASSERT(::IsWindow(m_hWnd));

    DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_STYLE);
    DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
    if (dwStyle == dwNewStyle)
      return TRUE;

    ::SetWindowLong(m_hWnd, GWL_STYLE, dwNewStyle);
    if (nFlags != 0)
    {
      ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0,
        SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
    }

    return TRUE;
  }

  BOOL ModifyStyleEx(
    _In_ DWORD dwRemove,
    _In_ DWORD dwAdd,
    _In_ UINT nFlags = 0) throw()
  {
    ATLASSERT(::IsWindow(m_hWnd));

    DWORD dwStyle = ::GetWindowLong(m_hWnd, GWL_EXSTYLE);
    DWORD dwNewStyle = (dwStyle & ~dwRemove) | dwAdd;
    if (dwStyle == dwNewStyle)
      return TRUE;

    ::SetWindowLong(m_hWnd, GWL_EXSTYLE, dwNewStyle);
    if (nFlags != 0)
    {
      ::SetWindowPos(m_hWnd, NULL, 0, 0, 0, 0,
        SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | nFlags);
    }

    return TRUE;
  }

protected:
  WindowImpl() {}
  virtual ~WindowImpl() override {}
  virtual void OnInitWnd() {}
  virtual void OnPrepareKeyDown(UINT nVirtualKey) {}

  virtual LRESULT MessageHandler(UINT uMsg, WPARAM wParam, LPARAM lParam, bool& bHandled) override
  {
    if (uMsg == WM_KEYDOWN) {
      OnPrepareKeyDown(UINT(wParam));
    }
    return 0;
  }

private:
  // 统一性原则，重命名InitWindow为OnInitWnd
  virtual void InitWindow() override final { OnInitWnd(); }
  // 屏蔽WindowImplBase默认按键，避免VK_ESCAPE触发WM_CLOSE
  virtual LRESULT ResponseDefaultKeyEvent(WPARAM wParam) override final { return 0; }
};